﻿using System;
using System.Data;
using System.Globalization;
using System.Reflection;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI.WebControls;

namespace CodePlex.ExtendedLookup
{
    /// <summary>
    /// Extension of the lookup field, adding filtering by view.
    /// </summary>
    public class ExtendedLookupFieldControl : LookupField
    {
        private DataView dataSource;
        private SPList lookupList;

        private SPList LookupList
        {
            get
            {
                if (lookupList == null)
                {
                    PropertyInfo info = typeof(LookupField).GetProperty("LookupList", BindingFlags.Instance | BindingFlags.NonPublic);
                    lookupList = (SPList)info.GetValue(this, null);
                }
                return lookupList;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void CreateChildControls()
        {
            FieldInfo info = typeof(LookupField).GetField("m_dataSource", BindingFlags.Instance | BindingFlags.NonPublic);
            DataView ds = DataSource;
            info.SetValue(this, ds);
            base.CreateChildControls();

            SPFieldLookupValue v = (SPFieldLookupValue)this.ItemFieldValue;
            if (v != null)
            {
                for (int idx = 0; idx < ds.Count; idx++)
                {
                    DataRowView dr = ds[idx];
                    if ((int)dr["ValueField"] == v.LookupId)
                    {
                        FieldInfo selectedValueIndex = typeof(LookupField).GetField("m_selectedValueIndex", BindingFlags.NonPublic | BindingFlags.Instance);
                        selectedValueIndex.SetValue(this, idx);

                        FieldInfo m_dropListField = typeof(LookupField).GetField("m_dropList", BindingFlags.NonPublic | BindingFlags.Instance);
                        DropDownList m_dropList = m_dropListField.GetValue(this) as DropDownList;
                        m_dropList.SelectedIndex = idx;
                    }
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool AddMissingValue
        {
            get
            {
                ExtendedLookupField elf = this.Field as ExtendedLookupField;
                return elf.AddMissingValue;
            }
        }

        private DataView DataSource
        {
            get
            {
                string lookupField;
                if (dataSource != null)
                {
                    return dataSource;
                }
                int num = 0;
                SPFieldLookup lookup = (SPFieldLookup)Field;
                if (lookup != null)
                {
                    lookupField = lookup.LookupField;
                    if (string.IsNullOrEmpty(lookupField))
                    {
                        lookupField = "Title";
                    }
                }
                else
                {
                    return null;
                }

                int num2 = (ItemIds.Count <= 0) ? 0 : ItemIds[0];
                DataTable table = new DataTable { Locale = CultureInfo.InvariantCulture };
                table.Columns.Add(new DataColumn("ValueField", typeof(int)));
                table.Columns.Add(new DataColumn("TextField", typeof(string)));
                if (!lookup.Required && !lookup.AllowMultipleValues)
                {
                    DataRow row = table.NewRow();
                    row[0] = 0;
                    row[1] = SPResource.GetString("LookupFieldNoneOption", new object[0]);
                    table.Rows.Add(row);
                    num++;
                }
                SPList list = LookupList;
                if (list != null)
                {
                    try
                    {
                        SPFieldLookupValue v = (SPFieldLookupValue)this.ItemFieldValue;
                        bool currentFound = false;
                        SPField field = list.Fields.GetField(lookupField);
                        SPView view = list.Views[((ExtendedLookupField)Field).LookupViewId];
                        SPListItemCollection items = list.GetItems(view);
                        for (int i = 0; i < items.Count; i++)
                        {
                            SPListItem item = list.GetItemById(items[i].ID);
                            string fieldValueAsText;
                            try
                            {
                                fieldValueAsText = field.GetFieldValueAsText(item[lookupField]);
                            }
                            catch (ArgumentException)
                            {
                                fieldValueAsText = item.Title;
                            }
                            if (!string.IsNullOrEmpty(fieldValueAsText))
                            {
                                DataRow row2 = table.NewRow();
                                row2[0] = item.ID;
                                row2[1] = fieldValueAsText;
                                table.Rows.Add(row2);
                                num++;
                                if (v != null && item.ID == v.LookupId)
                                {
                                    currentFound = true;
                                }
                            }
                        }
                        if (!currentFound && v != null && AddMissingValue)
                        {
                            DataRow row = table.NewRow();
                            row[0] = v.LookupId;
                            row[1] = v.LookupValue;
                            table.Rows.Add(row);
                        }
                        dataSource = new DataView(table);
                        return dataSource;
                    }
                    catch (ArgumentException)
                    {
                        return null;
                    }
                }
                return null;
            }
        }
    }
}